import os
from datetime import datetime
import struct
import sys
import threading
import time
import pyqtgraph as pg

import PySide2
from PySide2.QtCore import QTimer
from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader
import serial
import serial.tools.list_ports as list_ports



class MainWindow:

    def __init__(self):

        self.ui = QUiLoader().load('../ui/main.ui')
        self.main()
        self.setup_pyside2()
        self.time1 = QTimer()
        self.recv_num = 0
        self.per_pack = 100
        self.flag = 0
        self.x = []
        self.y = []
        self.t=0
        self.log=-1
        self.bytes_len = 0
        self.env_rssi=-1


    def setup_pyside2(self):
        if os.name=='nt':
            dirname=os.path.dirname(PySide2.__file__)
            plugin_path=os.path.join(dirname,'plugins','platforms')
            os.environ['QT_QPA_PLATFORM_PLUGIN_PATH']=plugin_path
        else:
            pass
    def start(self):

        if  self.ui.comboBox_2.currentText()!='':
            if self.ui.comboBox_2.currentText()=='泽耀':
                th1 = threading.Thread(target=self.get_rssi, )
            elif self.ui.comboBox_2.currentText()=='亿佰特':
                th1 = threading.Thread(target=self.get_rssi1, )
            self.log = f'{self.ui.comboBox_2.currentText()}_{time.time()}.csv'
            with open(self.log,'w',encoding='utf-8') as f:
                f.write('时间,间隔,延时,收到包数量,丢包率,环境rssi,数据rssi,'+'\n')
            th1.start()
            print('开始接收')
            self.time1.start(100)
            self.time1.timeout.connect(self.test)
        else:
            self.ui.statusbar.showMessage('请选择模块品牌', 5000)

    def stop(self):
        self.time1.stop()
        # self.ui.close()
        # os.system(f'kill -9 {os.getpid()}')

    def test(self):
        if self.flag == 1:
            # try:
            data = self.receive_frame(self.ser)
            if data:
                timestamp, command, control_param, time_interval = data
                self.ui.lineEdit.setText(f'{command}')
                self.ui.lineEdit_2.setText(f'{time_interval[-2]}')

                self.ui.lineEdit_3.setText(f'{time_interval[-1]}')

                # self.x.append(self.x[-1] + 1)
                # self.y.append(self.y[-1] + 10)
                # self.y+=10
                # print(self.x,self.y)
                # print(time.time())
                # print(time.time(),time_interval[-2])
                t_n=time.time()
                if self.t==0:
                    self.t=t_n
                t_s=time_interval[-2]
                self.x.append(t_n-self.t)
                self.y.append(t_s)
                self.m.plot(x=self.x, y=self.y, symbolPen='w')
                # ,pen='b', symbolBrush=(0,20,20)
                self.m.update()
                with open(self.log,'a+',encoding='utf-8') as f:
                    # 间隔延时收到包数量丢包率
                    f.write(f'{t_n},{300},{t_s},{self.bytes_len},{round(self.per_pack,4)},{self.env_rssi},{self.data_rssi}\n')

                # with open('')
                # print(f'{time.time()}: {time_interval[-2]}  {self.per_pack}%')
        # except:
        #     pass

    def sing(self):
        self.ui.pushButton_4.clicked.connect(self.get_serial)
        self.ui.pushButton_3.clicked.connect(self.connect_serial)
        self.ui.pushButton.clicked.connect(self.start)
        self.ui.pushButton_2.clicked.connect(self.stop)

    def get_serial(self):
        # 获取可用串口列表
        available_ports = list(list_ports.comports())

        # 将可用串口添加到下拉框中
        if len(available_ports) == 0:
            self.ui.comboBox.addItem('no serial ports find ')
        else:
            self.ui.comboBox.clear()
            for port in available_ports:
                self.ui.comboBox.addItem(port.device)

    def connect_serial(self):
        # print(self.ui.comboBox.currentText())
        port_name = self.ui.comboBox.currentText()
        if port_name != 'no serial ports find ':
            try:

                self.ser = serial.Serial(port_name, 115200, timeout=0.5)
                time.sleep(0.5)

                if self.ser.is_open:

                    self.ui.pushButton_3.setText('Connected')

                    self.flag = 1

                else:
                    # print('cant open {}'.format(self.ui.comboBox.currentText()))
                    self.ui.pushButton_3.setText('Disconnect')
            except Exception as e:
                if e.errno == 13:
                    self.ui.lineEdit_6.setText(f"[Errno 13] Permission denied")
                print(e)

    def get_rssi(self, ):
        while 1:
            self.ser.write(b'\x00\x01\x01')
            time.sleep(1)

    def get_rssi1(self, ):
        while 1:
            self.ser.write(b'\xC0\xC1\xC2\xC3\x00\x01')
            time.sleep(1)

    def calculate_checksum(self, data):
        return sum(data) % 256  # 简单的校验和

    def get_time(self, timestamp, a=300):
        current_utc_time = datetime.utcnow()
        # 获取年、月、日、时、分、秒和毫秒
        year = current_utc_time.year
        year = int(str(year)[-2::]) - timestamp[0]
        month = current_utc_time.month - timestamp[1]
        day = current_utc_time.day - timestamp[2]
        hour = current_utc_time.hour - timestamp[3]
        minute = current_utc_time.minute - timestamp[4]
        second = current_utc_time.second - timestamp[5]
        millisecond = round(current_utc_time.microsecond / 1000) - timestamp[6]
        # a = 300#  sleep 0.3
        reserved = second * 1000 + round(millisecond) - a

        return (year, month, day, hour, minute, second, millisecond, reserved, a)

    def receive_frame(self, serial_port):
        try:

            # 读取帧头
            header = serial_port.read(2)

            # header=b'\x06\x06\x1c\x18\x07\x0c\x04/\x17 \x8b\x01\x02\x03\x04\x01\x02\x03\x04\x05\x06\x07\x08\x00\x00jf\xaa'
            if header:
                # print(header)
                if header == FRAME_HEADER:
                    # 读取长度
                    # length = struct.unpack('!B', serial_port.read(1))[0]
                    length = serial_port.read(1)
                    # timestamp
                    # timestamp=struct.unpack('!BBBBBBH',serial_port.read(8))
                    timestamp = serial_port.read(8)

                    # 读取命令
                    # command = struct.unpack('!I', serial_port.read(4))
                    command = serial_port.read(4)
                    # 读取数据

                    # control_param = struct.unpack('!Q', serial_port.read(8))
                    control_param = serial_port.read(8)
                    # reserved = struct.unpack('!H', serial_port.read(2))
                    reserved = serial_port.read(2)
                    # 读取校验和
                    checksum = struct.unpack('!B', serial_port.read(1))[0]
                    # 读取帧尾
                    # tail = struct.unpack('!H', serial_port.read(2))
                    tail = serial_port.read(2)

                    if tail == FRAME_TAIL and checksum == self.calculate_checksum(
                            length + timestamp + command + control_param + reserved):
                        timestamp = struct.unpack('!BBBBBBH', timestamp)
                        time_interval = self.get_time(timestamp)
                        if self.ui.comboBox_2.currentText()=='亿佰特':
                            tail_ebyte = serial_port.read(1)
                            self.data_rssi = tail_ebyte[0] - 256
                            self.ui.lineEdit_5.setText(str(self.data_rssi))
                        else:
                            pass
                        # print(tail_ebyte)
                        # if tail_ebyte[0:2]==b'\x0D\x0A':
                        #
                        #     env_rssi = tail_ebyte[-1] - 256
                        #     self.ui.lineEdit_4.setText(str(env_rssi))
                        # else:
                        #     header=tail_ebyte
                        self.bytes_len += 28

                        if self.recv_num < 65535:

                            self.recv_num += 1
                        else:
                            self.recv_num = 0
                        down = struct.unpack('!H', reserved)[0]
                        # print(self.recv_num,down)
                        self.per_pack = (1 - round(self.recv_num / down, 3)) * 100
                        self.ui.lineEdit_7.setText(f'{round(self.per_pack,4)}%')

                        return timestamp, command, control_param, time_interval
                    else:
                        print("校验失败或帧尾错误")
                        self.ui.lineEdit_6.setText("校验失败或帧尾错误")
                elif header == b'\x00\x01':
                    length = serial_port.read(5)
                    # print(length)
                    # print(length[1]==255)
                    if length[1] == 255 and length[3] == 255:
                        # print(length[2]-256)
                        self.env_rssi = length[2] - 256
                        self.data_rssi = length[4] - 256
                        self.ui.lineEdit_4.setText(str(self.env_rssi))
                        self.ui.lineEdit_5.setText(str(self.data_rssi))

                        # print(f'env_rssi: {env_rssi},data_rssi: {data}')
                        # print()
                elif header == b'\xc1\x00':
                    length = serial_port.read(2)
                    if length[0] == 1:
                        self.env_rssi = length[1] - 256
                        self.ui.lineEdit_4.setText(str(self.env_rssi))

                # print(length)
                # print(length[1]==255)
                # if length[1] == 255 and length[3] == 255:
                #     # print(length[2]-256)
                #     env_rssi = length[2] - 256
                #     data = length[4] - 256
                #     self.ui.lineEdit_4.setText(str(env_rssi))
                #     self.ui.lineEdit_5.setText(str(data))

                # print(f'env_rssi: {env_rssi},data_rssi: {data}')
                # print()
                else:
                    print("帧头错误")
        except:

            os.system(f'kill -9 {os.getpid()}')

    def main(self):
        self.sing()
        self.get_serial()
        self.plot()
        sympol_list=['','泽耀','亿佰特']
        # sympol_list.clear()
        for s in sympol_list:
            self.ui.comboBox_2.addItem(s)

    def plot(self):

        win = pg.GraphicsLayoutWidget(show=True)
        win.setBackground('white')
        self.ui.verticalLayout_4.addWidget(win)
        self.m = win.addPlot()
        # self.curve = self.m.plot(pen='y', symbolBrush=(255,0,0), symbolPen='w')
        # m.setBackGround('white')
        # a=pg.getConfigOption('background')
        # pg.setConfigOptions('background'= '#FFFFFF')
        # pg.setConfigOptions(antialias=True,background='d',foreground= 'k')
        # print(a)


if __name__ == "__main__":
    FRAME_HEADER = 0x0606  # 2字节帧头
    FRAME_HEADER = struct.pack('!H', FRAME_HEADER)
    FRAME_TAIL = 0x66AA  # 2字节帧尾
    FRAME_TAIL = struct.pack('!H', FRAME_TAIL)


    app = QApplication([])
    mainwindow = MainWindow()
    mainwindow.ui.show()
    app.exec_()
    # print(bytes_len)
